package net.betou.trade.web;

import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.betou.common.util.TradeUtils;
import net.betou.common.web.session.SessionProvider;
import net.betou.core.manager.AuthenticationMng;
import net.betou.trade.action.TradeLoginAct;
import net.betou.trade.entity.main.AgentAndAdmins;
import net.betou.trade.main.manager.agencyorproxy.AdminMng;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.util.UrlPathHelper;

/**
 * 上下文信息拦截器
 * 
 * 包括登录信息、权限信息
 * 
 * @author 叶装装
 * 
 */
public class AdminContextInterceptor extends HandlerInterceptorAdapter{
	//private static final Logger log = Logger.getLogger( AdminContextInterceptor.class );
	public static final String PERMISSION_MODEL = "_permission_key";
	
	@Override
	public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler ) throws Exception {
		// 获得用户
		AgentAndAdmins user = null;
		
		// 正常状态
		Integer userId = authMng.retrieveUserIdFromSession( session, request );
		if( userId != null ){
			user = adminMng.findById( userId );
		}
		
		
		// 此时用户可以为null
		TradeUtils.setAdmin( request, user );

		String uri = getURI( request );
		// 不在验证的范围内
		if( exclude( uri ) ){
			return true;
		}

		// 用户为null跳转到登陆页面
		if( user == null ){
			response.sendRedirect( getLoginUrl( request ) );
			return false;
		}
		
		if( user.getDisabled( ) ){
			response.sendError( HttpServletResponse.SC_NOT_ACCEPTABLE );
			return false;
		}
		
		// 没有访问权限，提示无权限。
		if( auth && !permistionPass( uri, user.getPerms( ) ) ){
			response.setHeader( "loginStatus", "unauthorized" );
			response.sendError( HttpServletResponse.SC_FORBIDDEN );
			return false;
		}
		return true;
	}

	@Override
	public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mav ) throws Exception {
		AgentAndAdmins user = TradeUtils.getAdmin( request );
		// 不控制权限时perm为null，PermistionDirective标签将以此作为依据不处理权限问题。
		if( auth && user != null &&  mav != null && mav.getModelMap( ) != null && mav.getViewName( ) != null && !mav.getViewName( ).startsWith( "redirect:" ) ){
			mav.getModelMap( ).addAttribute( PERMISSION_MODEL, user.getPerms( ) );
		}
	}

	@Override
	public void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex ) throws Exception {
		// Sevlet容器有可能使用线程池，所以必须手动清空线程变量。
		
	}

	private String getLoginUrl( HttpServletRequest request ) {
		StringBuilder buff = new StringBuilder( );
		if( loginUrl.startsWith( "/" ) ){
			String ctx = request.getContextPath( );
			if( !StringUtils.isBlank( ctx ) ){
				buff.append( ctx );
			}
		}
		buff.append( loginUrl ).append( "?" );
		buff.append( TradeLoginAct.RETURN_URL ).append( "=" ).append( returnUrl );
		if( !StringUtils.isBlank( processUrl ) ){
			buff.append( "&" ).append( TradeLoginAct.PROCESS_URL ).append( "=" ).append( getProcessUrl( request ) );
		}
		return buff.toString( );
	}

	private String getProcessUrl( HttpServletRequest request ) {
		StringBuilder buff = new StringBuilder( );
		if( loginUrl.startsWith( "/" ) ){
			String ctx = request.getContextPath( );
			if( !StringUtils.isBlank( ctx ) ){
				buff.append( ctx );
			}
		}
		buff.append( processUrl );
		return buff.toString( );
	}
		
	private boolean exclude( String uri ) {
		if( excludeUrls != null ){
			for ( String exc : excludeUrls ){
				if( exc.equals( uri ) ){
					return true;
				}
			}
		}
		return false;
	}

	private boolean permistionPass( String uri, Set< String > perms ) {
		for ( String perm : perms ){
			if( uri.startsWith( perm ) ){
				return true;
			}
		}
		return false;
	}

	/**
	 * 获得第三个路径分隔符的位置
	 * 
	 * @param request
	 * @throws IllegalStateException
	 *             访问路径错误，没有三(四)个'/'
	 */
	private static String getURI( HttpServletRequest request ) throws IllegalStateException {
		UrlPathHelper helper = new UrlPathHelper( );
		String uri = helper.getOriginatingRequestUri( request );
		String ctxPath = helper.getOriginatingContextPath( request );
		int start = 0, i = 0, count = 2;
		if( !StringUtils.isBlank( ctxPath ) ){
			count++;
		}
		while( i < count && start != -1 ){
			start = uri.indexOf( '/', start + 1 );
			i++;
		}
		if( start <= 0 ){
			throw new IllegalStateException( "admin access path not like '/betouadmin/betoutrade/' pattern: " + uri );
		}
		return uri.substring( start );
	}
	
	@Autowired
	private SessionProvider session;
	@Autowired
	private AuthenticationMng authMng;
	@Autowired
	private AdminMng adminMng;
	
	private boolean auth = true;
	private String [ ] excludeUrls;

	private String loginUrl;
	private String processUrl;
	private String returnUrl;
	

	public void setAuth( boolean auth ) {
		this.auth = auth;
	}

	public void setExcludeUrls( String [ ] excludeUrls ) {
		this.excludeUrls = excludeUrls;
	}

	public void setLoginUrl( String loginUrl ) {
		this.loginUrl = loginUrl;
	}

	public void setProcessUrl( String processUrl ) {
		this.processUrl = processUrl;
	}

	public void setReturnUrl( String returnUrl ) {
		this.returnUrl = returnUrl;
	}

}